/*
  Copyright (C) 2011, Kyungjoo Kim
  
  This file is part of UHM (Unassembled HyperMatrix) sparse direct solver.
  
  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Also add information on how to contact you by electronic and paper mail.
  
  
  Kyungjoo Kim
  iamkyungjoo@gmail.com
*/
#ifndef UHM_INTERF_SPARSE_HXX
#define UHM_INTERF_SPARSE_HXX

namespace uhm {

  namespace interf {
    typedef class Element_* Element;

    typedef class Sparse_*  Sparse;
    typedef class DSparse_* DSparse;
    typedef class ZSparse_* ZSparse;

    // ----------------------------------------------------------------
    // ** Sparse matrix ij triplet and CSR format
    class Sparse_ {
    private:
    protected:
      int fort, datatype, cs, n_dof, n_rhs, axpy;
      void _init(int datatype, int fort, int cs,
                 int n_dof, int n_rhs);
      
    public:
      Sparse_() { }
      virtual ~Sparse_() { }

      bool is_complex();
      bool is_fort_numbering();
      bool is_column_major();
      bool is_axpy();

      virtual void set_axpy(int axpy);

      virtual bool import_element(Element e)=0;


      virtual bool import_rhs(std::vector<double> &rhs, int assemble,
                              int ldb, int n_rhs, Element e);
      virtual bool import_rhs(std::vector<double> &rhs, int assemble,
                              int ldb, int n_rhs,
                              int mat, Element e);
      virtual bool export_rhs(std::vector<double> &rhs, int assemble,
                              int ldb, int n_rhs, Element e);
      virtual bool export_rhs(std::vector<double> &rhs, int assemble,
                              int ldb, int n_rhs,
                              int mat, Element e);

        
      virtual void reset(int n_rhs)=0;

      virtual bool triplet(int is_sym, 
                           int &n_dof, int &n_rhs, int &n_nz,
                           std::vector<int> &ia, 
                           std::vector<int> &ja,
                           std::vector<double> &a,
                           std::vector<double> &b)=0;
    
      virtual bool compress(int is_sym,
                            int &n_dof, int &n_rhs, int &n_nz,
                            std::vector<int> &ia, 
                            std::vector<int> &ja,
                            std::vector<double> &a,
                            std::vector<double> &b)=0;

      virtual void disp(FILE *stream, int ab)=0;
      virtual void disp(int ab)=0;
    };

    // ----------------------------------------------------------------
    class DSparse_ : public Sparse_ {
    private:
    protected:
      std::map< std::pair<int,int>, double > a_ij_val, b_ij_val;
    public:
      DSparse_() { }
      DSparse_(int fort, int cs, int n_rhs) { _init(UHM_REAL, fort, cs, 0, n_rhs); }
      virtual ~DSparse_() { }
    
      virtual void reset(int n_rhs);

      virtual bool import_element(Element e);

      virtual bool triplet(int is_sym,
                           int &n_dof, int &n_rhs, int &n_nz,
                           std::vector<int> &ia, 
                           std::vector<int> &ja,
                           std::vector<double> &a,
                           std::vector<double> &b);
    
      virtual bool compress(int is_sym,
                            int &n_dof, int &n_rhs, int &n_nz,
                            std::vector<int> &ia, 
                            std::vector<int> &ja,
                            std::vector<double> &a,
                            std::vector<double> &b);

      virtual void disp(FILE *stream, int ab);
      virtual void disp(int ab);
    };

    // ----------------------------------------------------------------
    class ZSparse_ : public Sparse_ {
    private:
    protected:
      std::map< std::pair<int,int>, std::complex<double> > a_ij_val, b_ij_val;
    public:
      ZSparse_() { }
      ZSparse_(int fort, int cs, int n_rhs) { _init(UHM_COMPLEX, fort, cs, 0, n_rhs); }
      virtual ~ZSparse_() { }
    
      virtual void reset(int n_rhs);
    
      virtual bool import_element(Element e);

      virtual bool triplet(int is_sym,
                           int &n_dof, int &n_rhs, int &n_nz,
                           std::vector<int> &ia, 
                           std::vector<int> &ja,
                           std::vector<double> &a,
                           std::vector<double> &b);
    
      virtual bool compress(int is_sym, 
                            int &n_dof, int &n_rhs, int &n_nz,
                            std::vector<int> &ia, 
                            std::vector<int> &ja,
                            std::vector<double> &a,
                            std::vector<double> &b);

      virtual void disp(FILE *stream, int ab);
      virtual void disp(int ab);
    };
  }
}

#endif
